using DataBase.Utils;
using NModbus;
using NModbus.Serial;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Util;

namespace GreenXi.Help
{
    public class ModBus
    {
        public static object Lock = new object();

        public async void Reset()
        {
            try
            {
                if (GlobalVariables.ModbusSerialMaster1 != null)
                {
                    GlobalVariables.ModbusSerialMaster1.WriteMultipleRegisters(1, 534, new ushort[1] { 2 });
                    await Task.Run(() => Task.Delay(100));
                    GlobalVariables.ModbusSerialMaster1.WriteMultipleRegisters(1, 534, new ushort[1] { 258 });
                }
                
                if (GlobalVariables.CompressorsNumber == 2)
                {
                    if (GlobalVariables.ModbusSerialMaster2!= null)
                    {
                        GlobalVariables.ModbusSerialMaster2.WriteMultipleRegisters(1, 534, new ushort[1] { 2 });
                        await Task.Run(() => Task.Delay(100));
                        GlobalVariables.ModbusSerialMaster2.WriteMultipleRegisters(1, 534, new ushort[1] { 258 });
                    }
                }
            }
            catch(Exception ex)
            {
                Helpers.Logger.Instance.Error(ex, $"复位伺服异常");
            }
        }


        /// <summary>
        /// 获取伺服电机存储的当前位置脉冲 并写入运动控制卡
        /// </summary>
        /// <returns></returns>
        public static int GetPositionOld(short AxisNum)
        {
          
            //实际位置，这里是先将前半位置和后半位置都先转换成16位的2进制再合并成一个值，最后转换成10进制
            int res;
            //位置的前半部分
            int numPart1;
            //位置的后半部分
            int numPart2;
            //获取到的字节
            ushort[] getInfo;
      
            try
            {
                var ModbusSerialMaster = AxisNum == 1 ? GlobalVariables.ModbusSerialMaster1 : GlobalVariables.ModbusSerialMaster2;
                if (ModbusSerialMaster == null)
                {
                    Helpers.Logger.Instance.Infomation($"压机{AxisNum}GetPosition获取getInfo为空");
                    return -9999;
                }

                lock (Lock)
                {
                    getInfo = ModbusSerialMaster.ReadHoldingRegisters(GlobalVariables.ServoMotorSlaveAddress, GlobalVariables.ServoMotorPosAds, 2);
                }

                numPart1 = ConvertTwosComplement(getInfo[0]);
                numPart2 = ConvertTwosComplement(getInfo[1]);
                res = -Two_HEX_turn_32(getInfo[1], getInfo[0]);
                return res;
            }
            catch (Exception ex)
            {
                Helpers.Logger.Instance.Error(ex, $"压机{AxisNum}GetPosition异常");
                return -9999;
            }
         
        }
      
        /// <summary>
        /// 获取报警状态 两个状态一致,获取一个就行了（50ms一次
        /// </summary>
        /// <returns></returns>
        public static int CallPolice(int AxisNum)
        {
            try
            {
                var ModbusSerialMaster = AxisNum == 1 ? GlobalVariables.ModbusSerialMaster1 : GlobalVariables.ModbusSerialMaster2;
                if (ModbusSerialMaster == null)
                {
                    Helpers.Logger.Instance.Infomation($"压机{AxisNum}CallPolice中GlobalVariables.ModbusSerialMaster 找不到对象");
                    return -9999;
                }
                ushort[] getInfo;
                int errorNum;
                lock (Lock)
                {
                    getInfo = ModbusSerialMaster.ReadHoldingRegisters(GlobalVariables.ServoMotorSlaveAddress, 2, 1);
                    Thread.Sleep(1);
                }
                errorNum = ConvertTwosComplement(getInfo[0]);
                return errorNum;
            }
            catch (Exception ex)
            {
                Helpers.Logger.Instance.Error(ex,$"压机{AxisNum}CallPolice异常");
                return -9999;
            }
        }


        /// <summary>
        /// 伺服心跳
        /// </summary>
        /// <param name="AxisNum"></param>
        /// <returns></returns>
        public static bool HeartBeat(int AxisNum)
        {
            try
            {
                var ModbusSerialMaster = AxisNum == 1 ? GlobalVariables.ModbusSerialMaster1 : GlobalVariables.ModbusSerialMaster2;
                if (ModbusSerialMaster == null)
                {
                    Helpers.Logger.Instance.Warning($"压机{AxisNum}ModbusSerialMaster为空");
                    return false;
                }
                ushort[] getInfo;
                int errorNum;
                getInfo = ModbusSerialMaster.ReadHoldingRegisters(GlobalVariables.ServoMotorSlaveAddress, 2, 1);
                errorNum = ConvertTwosComplement(getInfo[0]);
                return true;
            }
            catch (Exception ex)
            {
                if (GlobalVariables.CallPolice == 0)
                {
                    GlobalVariables.CallPolice = (int)GlobalVariables.CallPoliceStatus.伺服断开连接;
                }

                Helpers.Logger.Instance.Error(ex,$"压机{AxisNum}HeartBeat获取失败");
                return false;
            }

        }
      
        /// <summary>
        /// 伺服电机ModbusTcp串口连接
        /// </summary>
        public static bool ConnectServoMotorByTcp(short num)
        {
            try
            {
				var ServoMotor = num == 1 ? GlobalVariables.ServoMotor1 : GlobalVariables.ServoMotor2;
				TcpClient client = new();

				client.SendTimeout = 100;
				client.ReceiveTimeout = 100;
				//client.WriteTimeout = 1000; //写超时
				//client.Retries = 3; //尝试重复连接次数
				//client.WaitToRetryMilliseconds = 20; //尝试重复连接间隔
				IModbusFactory factory = new ModbusFactory();
				if (num == 1)
				{
					client.Connect(IPAddress.Parse(GlobalVariables.ServoMotorIp1), 1030);
					GlobalVariables.ModbusSerialMaster1 = factory.CreateMaster(client);
				}
				else
				{
					client.Connect(IPAddress.Parse(GlobalVariables.ServoMotorIp2), 1030);
					GlobalVariables.ModbusSerialMaster2 = factory.CreateMaster(client);
				}
				try
				{
					return ServoMotor.IsOpen;
				}
				catch (Exception)
				{
					Helpers.Logger.Instance.Warning($"Catch ConnectServoMotorByTcp");
					return false;
				}
			}
            catch (Exception ex)
            {
				MessageBox.Show("Modbus连接失败");
				Helpers.Logger.Instance.Warning($"Modbus连接失败:{ex}");
				return false;
			}
            
        }

        
        /// <summary>
        /// 由于ModBus寄存器中的取值只有地址，我们规定前八位是正负符号的判定地址，所以要将取到的值进行转换
        /// </summary>
        /// <param name="decimalNumber">取到的值</param>
        /// <returns></returns>
        private static int ConvertTwosComplement(int decimalNumber)
        {
            string binaryString = Convert.ToString(decimalNumber, 2);
            int result;
            // 如果二进制字符串为空或长度为0，返回0
            if (string.IsNullOrEmpty(binaryString))
            {
                return 0;
            }

            // 如果二进制字符串的长度为16，且前八位都是1，则要求补码
            if (binaryString.Length != 16 && !binaryString.StartsWith("11111111"))
            {
                return Convert.ToInt32(binaryString, 2);
            }
            else
            {
                result = ConvertComplementCode(decimalNumber);
                return result;
            }
        }

        /// <summary>
        /// 求一个16位数数的补码（网上找的
        /// </summary>
        /// <param name="OriginalCode">传入一个Int16整型</param>
        /// <returns></returns>
        private static int ConvertComplementCode(int OriginalCode)
        {
            int a = short.MaxValue;
            int b = short.MinValue;
            int c = a - b;
            int d;
            if (OriginalCode > 0)
            {
                d = -(c - OriginalCode + 1);
            }
            else
            {
                d = c + OriginalCode + 1;
            }
            return d;
        }

        private static Int32 Two_HEX_turn_32(ushort DATA1, ushort DATA2)
        {
            Int32 DATA_32;
            DATA_32 = (DATA1 << 16) | DATA2; //DATA1在高位，DATA2在低位
            return DATA_32;
        }
    }
}
